﻿using System;
using System.Collections.Generic;
using System.Linq;
using DomenModel;
using System.Linq.Expressions;
using System.Security.Cryptography;
using Model.Repositories.Interfaces;
using System.Data.Entity;
using System.Text;

namespace OmsTestProject.MockRepository
{
    public class UserRepository : IUserCrud
    {
        MockRepositoryContext _db = MockRepositoryContext.MockContextInstance;
 
        public User GetById(long Id)
        {
                User userById = _db.Users.FirstOrDefault(p => p.UserId == Id);
                return userById;
        }

        public User GetByLogin(string LoginName)
        {
                    User userByLogin = _db.Users.FirstOrDefault(p => p.LoginName == LoginName);
                    return userByLogin;
        }

        public string GetRoleOfUser(string LoginName)
        {
                    User userByLogin = _db.Users.FirstOrDefault(p => p.LoginName == LoginName);
                    return userByLogin.Role.Name;
        }

        public User GetByEmail(string email)
        {
                    User userByEmail = _db.Users.FirstOrDefault(p => p.Email == email);
                    return userByEmail;
        }

        public void Save(User user)
        {
                _db.Users.Add(user);
        }

        public void Update(User user)   
        {
            try
            {
                _db.Users[(int)user.UserId].LoginName = user.LoginName;
                _db.Users[(int)user.UserId].FirstName = user.FirstName;
                _db.Users[(int)user.UserId].LastName = user.LastName;
                _db.Users[(int)user.UserId].Password = user.Password;
                _db.Users[(int)user.UserId].Email = user.Email;
                _db.Users[(int)user.UserId].Region = user.Region;
                _db.Users[(int)user.UserId].Balance = user.Balance;
                _db.Users[(int)user.UserId].RoleId = user.RoleId;
                _db.Users[(int)user.UserId].StatusId = user.StatusId;
                _db.Users[(int)user.UserId].IsActive = user.IsActive;

            }
            catch (InvalidCastException e) 
            {
                throw new InvalidCastException("User update error", e);
            }
        }

        public void Delete(long Id)
        {
                User userForRemove = _db.Users.FirstOrDefault(p => p.UserId == Id);
                _db.Users.Remove(userForRemove); 
        }

        public void Delete(string loginName)
        {
                User userForRemove = _db.Users.FirstOrDefault(p => p.LoginName == loginName);
                _db.Users.Remove(userForRemove);
        } 

        public List<User> GetCollection()
        {
                return _db.Users;
        }

        public List<User> GetListForPagination(int page, int itemsOnPage, Expression<Func<User, string>> predicate, bool descending)
        {
                  if (descending == true)
                  {
                      var listForPagination = _db.Users.AsQueryable<User>().Include("Role")
                          .OrderByDescending(predicate)
                          .Skip((page - 1) * itemsOnPage)
                          .Take(itemsOnPage)
                          .ToList();

                      return listForPagination;
                  }
                  else
                  {
                      var listForPagination = _db.Users.AsQueryable<User>().Include("Role")
                          .OrderBy(predicate)
                          .Skip((page - 1) * itemsOnPage)
                          .Take(itemsOnPage)
                          .ToList();

                      return listForPagination;
                  }
       }

        public List<User> GetListForPaginationWithFilter(int page, int itemsOnPage, Expression<Func<User, bool>> predicateListSelectedField, Expression<Func<User, string>> predicateSortBy, bool descending)
        {
                    if (descending == true)
                    {
                        var listForPagination = _db.Users.AsQueryable<User>().Include("Role")
                            .OrderByDescending(predicateSortBy)
                            .Where(predicateListSelectedField.Compile())
                            .Skip((page - 1) * itemsOnPage)
                            .Take(itemsOnPage)
                            .ToList();

                        return listForPagination;
                    }
                    else
                    {
                        var listForPagination = _db.Users.AsQueryable<User>().Include("Role")
                            .OrderBy(predicateSortBy)
                            .Where(predicateListSelectedField.Compile())
                            .Skip((page - 1) * itemsOnPage)
                            .Take(itemsOnPage)
                            .ToList();

                        return listForPagination;
                    }
        }


        public IQueryable<User> GetCollectionByFilter(Expression<Func<User, bool>> predicate)
        {
            return _db.Users.AsQueryable<User>().Where(predicate);
        }

        public long GetCountOfUser()
        {
                long _i = _db.Users.Count();
                return _i;

        }

        public long GetCountOfUser(Expression<Func<User, bool>> predicate)
        {
                long _i = _db.Users.AsQueryable<User>().Where(predicate).Count();
                return _i;
        }

        public string CreateSalt()
        {
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            byte[] buff = new byte[32];
            rng.GetBytes(buff);

            return Convert.ToBase64String(buff);
        }

        public string CreateHash(string salt, string password)
        {
            HashAlgorithm hashAl = HashAlgorithm.Create("MD5");
            string passwordAndSalt = String.Concat(password, salt);
            byte[] passwordAndSaltInBytes = Encoding.Unicode.GetBytes(passwordAndSalt);
            byte[] hashedPasswordAndSalt = hashAl.ComputeHash(passwordAndSaltInBytes);
            return Convert.ToBase64String(hashedPasswordAndSalt);
        }



    }
    
}
